home *** CD-ROM | disk | FTP | other *** search
- /****************************************************************************
- * render.c
- *
- * This module implements the main raytracing loop.
- *
- * 08/07/92 lsk Changed the normal antialiasing function to use a loop
- * where the number of rays per pixel when antialiasing can
- * be sepcified.
- *
- * from Persistence of Vision Raytracer
- * Copyright 1993 Persistence of Vision Team
- *---------------------------------------------------------------------------
- * NOTICE: This source code file is provided so that users may experiment
- * with enhancements to POV-Ray and to port the software to platforms other
- * than those supported by the POV-Ray Team. There are strict rules under
- * which you are permitted to use this file. The rules are in the file
- * named POVLEGAL.DOC which should be distributed with this file. If
- * POVLEGAL.DOC is not available or for more info please contact the POV-Ray
- * Team Coordinator by leaving a message in CompuServe's Graphics Developer's
- * Forum. The latest version of POV-Ray may be found there as well.
- *
- * This program is based on the popular DKB raytracer version 2.12.
- * DKBTrace was originally written by David K. Buck.
- * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
- *
- ******************************************************************************/
-
- #include "frame.h"
- #include "vector.h"
- #include "povproto.h"
-
- extern FILE_HANDLE *Output_File_Handle;
- extern char Output_File_Name[FILE_NAME_LENGTH];
- extern char Input_File_Name[FILE_NAME_LENGTH];
- extern char Stat_File_Name[FILE_NAME_LENGTH];
- extern char OutputFormat, Color_Bits, PaletteOption;
- extern char VerboseFormat;
- extern unsigned int Options;
- extern int File_Buffer_Size;
- extern int Use_Slabs;
- volatile int Stop_Flag;
- extern int First_Line, Last_Line;
- extern int First_Column, Last_Column;
- extern long Number_Of_Pixels, Number_Of_Rays, Number_Of_Pixels_Supersampled;
- extern short *hashTable;
- extern unsigned short crctab[256];
- extern OBJECT *Root_Object;
- extern long AntialiasDepth;
- extern DBL JitterScale;
-
- #define rand3d(a,b) crctab[(int)(hashTable[(int)(hashTable[(int)((a)&0xfff)]^(b))&0xfff])&0xff]
-
- FRAME Frame;
- RAY *CM_Ray;
- int Trace_Level, SuperSampleCount;
-
- DBL Max_Trace_Level = 5;
- DBL maxclr;
-
- static void check_stats PARAMS((int y));
- static void do_anti_aliasing PARAMS((int x, int y, COLOUR *Colour));
- static void output_line PARAMS((int y));
-
- COLOUR *Previous_Line, *Current_Line;
-
- char *Previous_Line_Antialiased_Flags, *Current_Line_Antialiased_Flags;
- RAY Ray;
-
- void Create_Ray (ray, width, height, x, y)
- RAY *ray;
- int width, height;
- DBL x, y;
- {
- register DBL X_Scalar, Y_Scalar;
- VECTOR Temp_Vect_1, Temp_Vect_2;
-
- /* Convert the X Coordinate to be a DBL from 0.0 to 1.0 */
- X_Scalar = (x - (DBL) width / 2.0) / (DBL) width;
-
- /* Convert the Y Coordinate to be a DBL from 0.0 to 1.0 */
- Y_Scalar = (( (DBL)(Frame.Screen_Height - 1) - y) -
- (DBL) height / 2.0) / (DBL) height;
-
- VScale (Temp_Vect_1, Frame.Camera->Up, Y_Scalar);
- VScale (Temp_Vect_2, Frame.Camera->Right, X_Scalar);
- VAdd (ray->Direction, Temp_Vect_1, Temp_Vect_2);
- VAdd (ray->Direction, ray->Direction, Frame.Camera->Direction);
- VNormalize (ray->Direction, ray->Direction);
- Initialize_Ray_Containers (ray);
- ray->Quadric_Constants_Cached = FALSE;
- }
-
- void Read_Rendered_Part()
- {
- int rc, x, line_number;
- unsigned char Red, Green, Blue;
- DBL grey;
-
- maxclr = (DBL)(1 << Color_Bits) - 1.0;
- while ((rc = Read_Line(Output_File_Handle, Previous_Line, &line_number)) == 1)
- {
- if (Options & DISPLAY)
- for (x = 0 ; x < Frame.Screen_Width ; x++)
- {
- if (PaletteOption == GREY)
- {
- grey = Previous_Line[x].Red * 0.287 +
- Previous_Line[x].Green * 0.589 +
- Previous_Line[x].Blue * 0.114;
- Red = Green = Blue = (unsigned char)(grey * maxclr);
- }
- else
- {
- Red = (unsigned char) (Previous_Line[x].Red * maxclr);
- Green = (unsigned char) (Previous_Line[x].Green * maxclr);
- Blue = (unsigned char) (Previous_Line[x].Blue * maxclr);
- }
- display_plot (x, line_number, Red, Green, Blue);
- COOPERATE /* Moved inside loop JLN 12/91 */
- }
- }
-
- First_Line = line_number+1;
-
- if (rc == 0)
- {
- Close_File(Output_File_Handle);
- if (Open_File (Output_File_Handle, Output_File_Name,
- &Frame.Screen_Width, &Frame.Screen_Height, File_Buffer_Size,
- APPEND_MODE) != 1)
- {
- fprintf (stderr, "Error opening output file\n");
- fflush(stdout);
- close_all();
- exit(1);
- }
- return;
- }
-
- fprintf (stderr, "Error reading aborted data file\n");
- }
-
- void Start_Tracing ()
- {
- COLOUR Colour;
- register int x, y;
- unsigned char Red, Green, Blue;
- DBL grey;
-
- for (y = (Options & ANTIALIAS)?First_Line-1:First_Line; y<Last_Line; y++)
- {
-
- check_stats(y);
-
- for (x = First_Column ; x <= Last_Column ; x++)
- {
-
- Check_User_Abort(1);
-
- Number_Of_Pixels++;
-
- Create_Ray (CM_Ray, Frame.Screen_Width, Frame.Screen_Height, (DBL) x, (DBL) y);
- Trace_Level = 0;
- Trace (&Ray, &Colour);
- Clip_Colour (&Colour, &Colour);
-
- Current_Line[x] = Colour;
-
- if (Options & ANTIALIAS)
- do_anti_aliasing(x, y, &Colour);
-
- if (y != First_Line-1)
- {
-
- if (PaletteOption == GREY)
- {
- grey = Colour.Red * 0.287 +
- Colour.Green * 0.589 +
- Colour.Blue * 0.114;
- Red = Green = Blue = (unsigned char)(grey * maxclr);
- }
- else
- {
- Red = (unsigned char) (Colour.Red * maxclr);
- Green = (unsigned char) (Colour.Green * maxclr);
- Blue = (unsigned char) (Colour.Blue * maxclr);
- }
- if (Options & DISPLAY)
- display_plot (x, y, Red, Green, Blue);
- }
- }
- output_line(y);
- }
-
- if (Options & DISKWRITE)
- {
- Write_Line (Output_File_Handle, Previous_Line, Last_Line - 1);
- }
- }
-
- static void check_stats(y)
- register int y;
- {
- FILE *stat_file;
-
- /* New verbose options CdW */
- if (Options & VERBOSE && VerboseFormat=='0')
- {
- printf ("POV-Ray rendering %s to %s",Input_File_Name,Output_File_Name);
- if((First_Line != 0) || (Last_Line != Frame.Screen_Height))
- printf(" from %4d to %4d:\n",First_Line, Last_Line);
- else
- printf (":\n");
- printf ("Res %4d X %4d. Calc line %4d of %4d",Frame.Screen_Width, Frame.Screen_Height, (y-First_Line)+1, Last_Line-First_Line);
- if (!(Options & ANTIALIAS))
- printf(".");
- }
- if (Options & VERBOSE_FILE)
- {
- stat_file = fopen(Stat_File_Name,"w+t");
- fprintf (stat_file,"Line %4d.\n", y);
- fclose(stat_file);
- }
-
- /* Use -vO for Old style verbose */
- if (Options & VERBOSE && (VerboseFormat=='O'))
- {
- printf ("Line %4d", y);
- }
- if (Options & VERBOSE && VerboseFormat=='1')
- {
- fprintf (stderr,"Res %4d X %4d. Calc line %4d of %4d",Frame.Screen_Width, Frame.Screen_Height, (y-First_Line)+1, Last_Line-First_Line);
- if (!(Options & ANTIALIAS))
- fprintf(stderr,".");
- }
-
- if (Options & ANTIALIAS)
- SuperSampleCount = 0;
- }
-
- static void do_anti_aliasing(x, y, Colour)
- register int x, y;
- COLOUR *Colour;
- {
- char Antialias_Center_Flag = 0;
-
- Current_Line_Antialiased_Flags[x] = 0;
-
- if (x != 0)
- {
- if (Colour_Distance (&Current_Line[x-1], &Current_Line[x])
- >= Frame.Antialias_Threshold)
- {
- Antialias_Center_Flag = 1;
- if (!(Current_Line_Antialiased_Flags[x-1]))
- {
- Supersample (&Current_Line[x-1],
- x-1, y, Frame.Screen_Width, Frame.Screen_Height);
- Current_Line_Antialiased_Flags[x-1] = 1;
- SuperSampleCount++;
- }
- }
- }
-
- if (y != First_Line-1)
- {
- if (Colour_Distance (&Previous_Line[x], &Current_Line[x])
- >= Frame.Antialias_Threshold)
- {
- Antialias_Center_Flag = 1;
- if (!(Previous_Line_Antialiased_Flags[x]))
- {
- Supersample (&Previous_Line[x],
- x, y-1, Frame.Screen_Width, Frame.Screen_Height);
- Previous_Line_Antialiased_Flags[x] = 1;
- SuperSampleCount++;
- }
- }
- }
-
- if (Antialias_Center_Flag)
- {
- Supersample (&Current_Line[x],
- x, y, Frame.Screen_Width, Frame.Screen_Height);
- Current_Line_Antialiased_Flags[x] = 1;
- *Colour = Current_Line[x];
- SuperSampleCount++;
- }
-
- return;
- }
-
-
- void Initialize_Renderer PARAMS((void))
- {
- register int i;
-
- CM_Ray = &Ray;
-
- maxclr = (DBL)(1 << Color_Bits) - 1.0;
-
- /* These malloc's are never freed! Why ? Need a Deinit_Renderer() ?*/
- Previous_Line = (COLOUR *) malloc (sizeof (COLOUR)*(Frame.Screen_Width + 1));
- Current_Line = (COLOUR *) malloc (sizeof (COLOUR)*(Frame.Screen_Width + 1));
-
- for (i = 0 ; i <= Frame.Screen_Width ; i++)
- {
- Previous_Line[i].Red = 0.0;
- Previous_Line[i].Green = 0.0;
- Previous_Line[i].Blue = 0.0;
- Current_Line[i].Red = 0.0;
- Current_Line[i].Green = 0.0;
- Current_Line[i].Blue = 0.0;
- }
-
- if (Options & ANTIALIAS)
- {
- Previous_Line_Antialiased_Flags =
- (char *) malloc (sizeof (char)*(Frame.Screen_Width + 1));
- Current_Line_Antialiased_Flags =
- (char *) malloc (sizeof (char)*(Frame.Screen_Width + 1));
-
- for (i = 0 ; i <= Frame.Screen_Width ; i++)
- {
- (Previous_Line_Antialiased_Flags)[i] = 0;
- (Current_Line_Antialiased_Flags)[i] = 0;
- }
- }
-
- Ray.Initial = Frame.Camera->Location;
- return;
- }
-
- static void output_line (y)
- register int y;
- {
- COLOUR *Temp_Colour_Ptr;
- char *Temp_Char_Ptr;
-
- if (Options & DISKWRITE)
- if (y > First_Line)
- {
- Write_Line (Output_File_Handle, Previous_Line, y-1);
- }
-
- if (Options & VERBOSE)
- {
- if (Options & ANTIALIAS && VerboseFormat != '1')
- printf (" supersampled %d times.", SuperSampleCount);
-
- if (Options & ANTIALIAS && VerboseFormat == '1')
- {
- fprintf (stderr," supersampled %d times.", SuperSampleCount);
-
- }
- if (VerboseFormat == '1')
- fprintf (stderr,"\r");
- else
- fprintf (stderr,"\n");
- }
- Temp_Colour_Ptr = Previous_Line;
- Previous_Line = Current_Line;
- Current_Line = Temp_Colour_Ptr;
-
- Temp_Char_Ptr = Previous_Line_Antialiased_Flags;
- Previous_Line_Antialiased_Flags = Current_Line_Antialiased_Flags;
- Current_Line_Antialiased_Flags = Temp_Char_Ptr;
-
- return;
- }
-
- void Trace (Ray, Colour)
- RAY *Ray;
- COLOUR *Colour;
- {
- OBJECT *Object;
- INTERSECTION Best_Intersection, New_Intersection;
- register int Intersection_Found;
-
- COOPERATE
- Number_Of_Rays++;
- Make_Colour (Colour, 0.0, 0.0, 0.0);
-
- if (Trace_Level > (int) Max_Trace_Level)
- return;
-
- Intersection_Found = FALSE;
- Best_Intersection.Depth = BOUND_HUGE;
-
- /* What objects does this ray intersect? */
- if (!Use_Slabs)
- for (Object = Frame.Objects ;
- Object != NULL ;
- Object = Object -> Sibling)
- {
- if (Intersection (&New_Intersection, Object, Ray))
- if (New_Intersection.Depth < Best_Intersection.Depth)
- {
- Best_Intersection = New_Intersection;
- Intersection_Found = TRUE;
- }
- }
- else
- Intersection_Found = Bounds_Intersect(Root_Object, Ray,
- &Best_Intersection,&Object);
-
- if (Intersection_Found)
- Determine_Apparent_Colour (&Best_Intersection, Colour, Ray);
- else
- if (Frame.Fog_Distance > 0.0)
- *Colour = Frame.Fog_Colour;
- else
- *Colour = Frame.Background_Colour;
- }
-
- /* exit with error if image not completed/user abort*/
- void Check_User_Abort (Do_Stats)
- int Do_Stats;
- {
- TEST_ABORT
- if (Stop_Flag)
- {
- close_all();
- if (Do_Stats)
- {
- PRINT_STATS
- }
- exit(2);
- }
- }
-
- /*--------------- Standard sampling in loop -----------------------*/
-
- unsigned short JRanges[] = {1,1,1,1,3,2,5,3,7,4}; /* LSK */
-
- void Supersample (result, x, y, Width, Height)
- COLOUR *result;
- int x, y, Width, Height;
- {
- COLOUR colour;
- register DBL dx, dy, Jitter_X, Jitter_Y;
- register int Jitt_Offset;
- unsigned char Red, Green, Blue;
- int JRange; /* LSK */
- int JSteps; /* LSK */
- DBL JScale; /* LSK */
- DBL JSize,JOffset; /* LSK */
- int i,j; /* LSK */
-
- dx = (DBL) x; /* LSK */
- dy = (DBL) y; /* LSK */
- Jitt_Offset = 10;
-
- Number_Of_Pixels_Supersampled++;
-
- Make_Colour (result, 0.0, 0.0, 0.0);
-
- if (AntialiasDepth>1) /* LSK */
- { /* LSK */
- /* JSize is the size of the jitter scattering area */
- JSize = 1.0/AntialiasDepth; /* LSK */
-
- /* JOffset is the 'radius' of the jitter scatter area */
- JOffset = JSize/2.0; /* LSK */
-
- /* JSteps is either 1 or 2 depending on whether the number of samples
- is odd or even. This is because the loop need to either run through
- or over 0
- */
- JSteps = 2-(AntialiasDepth % 2); /* LSK */
-
- /* JRange is the range that the loop will run through. I couldn't
- come up with a function describing the values, so I used an array
- for 2x2 up to 9x9.
- */
- JRange = JRanges[AntialiasDepth]; /* LSK */
-
- /* JScale is the scaling value for the color resulting from the
- ray before adding to the resultant color
- */
- JScale = 1.0/(DBL)(AntialiasDepth*AntialiasDepth); /* LSK */
-
- for (i=-JRange;i<=JRange;i+=JSteps)
- for (j=-JRange;j<=JRange;j+=JSteps)
- {
- if (Options & JITTER)
- {
- Jitter_X = (rand3d(x+Jitt_Offset, y) & 0x7FFF) / 32768.0 * JSize - JOffset;
- Jitt_Offset++;
- Jitter_Y = (rand3d(x+Jitt_Offset, y) & 0x7FFF) / 32768.0 * JSize - JOffset;
- Jitt_Offset++;
- }
- else
- {
- Jitter_X=Jitter_Y=0.0;
- }
- Jitter_X*=JitterScale;
- Jitter_Y*=JitterScale;
-
- Create_Ray (CM_Ray, Frame.Screen_Width, Frame.Screen_Height,
- dx + Jitter_X + i * JSize/JSteps,
- dy + Jitter_Y + j * JSize/JSteps );
-
- Trace_Level = 0;
- Trace (CM_Ray, &colour);
- Clip_Colour (&colour, &colour);
- Scale_Colour (&colour, &colour, JScale );
- Add_Colour (result, result, &colour);
-
- }
- } /* LSK */
- else /* 1x1 specified! */
- {
- Create_Ray (CM_Ray, Frame.Screen_Width, Frame.Screen_Height,dx,dy );
-
- Trace_Level = 0;
- Trace (CM_Ray, &colour);
- Clip_Colour (&colour, &colour);
- Add_Colour (result, result, &colour);
- Jitt_Offset += 10;
- }
-
- if ((y != First_Line - 1) && (Options & DISPLAY))
- {
- Red = (unsigned char)(result->Red * maxclr);
- Green = (unsigned char)(result->Green * maxclr);
- Blue = (unsigned char)(result->Blue * maxclr);
- display_plot (x, y, Red, Green, Blue);
- }
-
- }
-
-
-